#include <avr/io.h>
#include <util/delay_basic.h>
#include "../usbtiny/def.h"
#include "i2c.h"

//I2C pin
#define I2C_SCL			7
#define I2C_SDA			5

#define PIN_LOW(pin)		PORT_CLR(B, pin)
#define PIN_HIGH(pin)		PORT_SET(B, pin)

#define PIN_INPUT(pin)		DDR_CLR(B, pin)
#define PIN_OUTPUT(pin)		DDR_SET(B, pin)

#define i2c_nop() 

#define SET_SCL()		do{ PIN_HIGH(I2C_SCL); i2c_nop(); }while(0)
#define CLR_SCL()		do{ PIN_LOW(I2C_SCL);  i2c_nop(); }while(0)

#define SET_SDA()		do{ PIN_HIGH(I2C_SDA); i2c_nop(); }while(0)
#define CLR_SDA()		do{ PIN_LOW(I2C_SDA);  i2c_nop(); }while(0)

#define GET_SDA()		(PINB & (1<<I2C_SDA))

void __delay(void)
{
	//_delay_loop_1(0x55);
	asm volatile("\tPUSH R23");
	asm volatile("\tLDI  R23, 60");//control delay time here
	asm volatile("\tDEC  R23");
	asm volatile("\tBRNE .-4");
	asm volatile("\tPOP R23");
}

void i2c_start(void)
{
	SET_SDA();
	SET_SCL();

	PIN_OUTPUT(I2C_SCL);
	PIN_OUTPUT(I2C_SDA);

	delay();
	CLR_SDA();
	delay();
	CLR_SCL();
}

void i2c_stop(void)
{
	//CLR_SCL();
	CLR_SDA();
	PIN_OUTPUT(I2C_SCL);
	PIN_OUTPUT(I2C_SDA);
	delay();
	SET_SCL();
	delay();
	SET_SDA();
}

unsigned char i2c_write(unsigned char data)
{
	unsigned char mask = 0x80, ret;

	PIN_OUTPUT(I2C_SDA);
	do {
		if(mask & data) {
			SET_SDA();
		} else {
			CLR_SDA();
		}
		delay();
		SET_SCL();
		delay();
		mask = mask >> 1;
		CLR_SCL();
	} while(mask);
	SET_SDA();
	PIN_INPUT(I2C_SDA);

	delay();
	SET_SCL();
	delay();
	ret = GET_SDA();
	CLR_SCL();
	

	return ret;
}

unsigned char i2c_read(unsigned char ack_en)
{
	unsigned char mask = 0x80, read = 0;

	do {
		SET_SCL();
		if(GET_SDA()) {
			read |= mask;
		}
		delay();
		mask = mask >> 1;
		CLR_SCL();
		delay();
	} while(mask);

	//ACK
	if(ack_en) {
		CLR_SDA();
	} else {
		SET_SDA();
	}
	PIN_OUTPUT(I2C_SDA);
	delay();
	SET_SCL();
	delay();
	CLR_SCL();
	SET_SDA();
	PIN_INPUT(I2C_SDA);

	return read;
}

